
package com.chuhay.elemwar;

import java.awt.Dimension;

import static com.chuhay.elemwar.ElemWarConstants.*;
import com.chuhay.elemwar.ElemWarObject.Hex;

public class ElemWarLogic {
   // A reference to our game object
   protected ElemWarObject _gameobj;

   // A list of valid moves for the current hex
   protected Hex [][] moveArray;

   public ElemWarLogic (ElemWarObject obj) {
      _gameobj = obj;

      moveArray = new Hex [2] [4];
   }

   /**
    * Returns a validity code for the given move
    * 
    *
    * @param clickedHex The hex that the user clicked
    * @param selectedHex The currently selected hex
    * @param pieceType The type of the piece that is to be moved
    * @param isServer A flag denoting whether the server is calling this function
    * @return one of the VALID_XXXX codes in ElemWarConstants
    */
   public int getMoveValidity (Hex clickedHex, Hex selectedHex, int pieceType, boolean isServer) {
      // If clicked hex is not empty, keep checking
      if (clickedHex.pieceID != -1) {
         if (!isServer) {
            // If clicked on someone else's piece, do nothing
            if (_gameobj._pieces.get(clickedHex.pieceID).pieceType == pieceType) {
               // If we didn't click the selected hex, select the clicked hex
               if (clickedHex != selectedHex)
                  return VALID_VALID_SELECT;
               else
                  return VALID_VALID_DESELECT;

            }
         } else {
            // On server, should not be trying to move a piece onto another
            // piece
         }
      } else {
         // Hex is empty, see if it's valid
         if (!isServer) {
            // Client has board with SELECT_VALID information, use it.
            if (clickedHex.selected == SELECT_VALID)
               return VALID_VALID_MOVE;
         } else {
            // Server doesn't have SELECT_VALID information, need to do it the long way
            // Generate all possible moves for the selected hex
            Hex [][] possibleMoves = getPossibleMoves(selectedHex, pieceType);

            for (Hex hex : possibleMoves[0]) {
               // If destination hex is in list of 1-distance hexes, move is
               // valid
               if (clickedHex == hex)
                  return VALID_VALID_MOVE;
            }
            for (Hex hex : possibleMoves[1]) {
               // If destination hex is in list of 2-distance hexes, piece was
               // jumped
               if (clickedHex == hex)
                  return VALID_VALID_MOVE;
            }
         }
      }

      return VALID_INVALID;
   }

   /**
    * Generates all possible moves for the selected hex
    * 
    *
    * @param selectedHex The hex to generate the moves for
    * @param playerType The piece type for the player
    * @return two arrays containing a Hex if it's valid, else null
    */
   public Hex [][] getPossibleMoves (Hex selectedHex, int playerType) {
      int x = selectedHex.gridX;
      int y = selectedHex.gridY;

      Dimension size = ElemWarBoardView._size;

      Hex hex;
      
      // Null out array
      for(int i=0; i<4; i++) {
         moveArray[0][i] = null;
         moveArray[1][i] = null;
      }

      // Direction of valid moves depends on piece type
      switch (playerType) {
      case PIECE_FIRE:
         // If even row, get offsets for valid moves
         //  \/_
         //   \
         if ((y & 0x01) == 0) {
            if (x - 1 >= 0 && y - 1 >= 0) {
               hex = _gameobj._hexes.get((y - 1) * size.width + x - 1);
               // If hex exists, is not an ice-only region and is not filled, add it to list
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
               moveArray[0][0] = hex;
            } else
               moveArray[0][0] = null;
            if (x - 1 >= 0 && y - 2 >= 0) {
               hex = _gameobj._hexes.get((y - 2) * size.width + x - 1);
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
               moveArray[1][0] = hex;
            } else
               moveArray[1][0] = null;

            if (x >= 0 && y - 1 >= 0) {
               hex = _gameobj._hexes.get((y - 1) * size.width + x);
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[0][1] = hex;
            } else
               moveArray[0][1] = null;
            if (x + 1 < size.width && y - 2 >= 0) {
               hex = _gameobj._hexes.get((y - 2) * size.width + x + 1);
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[1][1] = hex;
            } else
               moveArray[1][1] = null;

            if (x + 1 < size.width && y >= 0) {
               hex = _gameobj._hexes.get(y * size.width + x + 1);
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[0][2] = hex;
            } else
               moveArray[0][2] = null;
            if (x + 2 < size.width && y >= 0) {
               hex = _gameobj._hexes.get(y * size.width + x + 2);
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[1][2] = hex;
            } else
               moveArray[1][2] = null;

            if (x >= 0 && y + 1 <= size.height) {
               hex = _gameobj._hexes.get((y + 1) * size.width + x);
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[0][3] = hex;
            } else
               moveArray[0][3] = null;
            if (x + 1 < size.width && y + 2 <= size.height) {
               hex = _gameobj._hexes.get((y + 2) * size.width + x + 1);
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[1][3] = hex;
            } else
               moveArray[1][3] = null;
         } else { // Start odd-numbered row code
            if (x >= 0 && y - 1 >= 0) {
               hex = _gameobj._hexes.get((y - 1) * size.width + x);
               // If hex exists, is not a fire-only region and is not filled, add it to list
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
               moveArray[0][0] = hex;
            } else
               moveArray[0][0] = null;
            if (x - 1 >= 0 && y - 2 >= 0) {
               hex = _gameobj._hexes.get((y - 2) * size.width + x - 1);
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
               moveArray[1][0] = hex;
            } else
               moveArray[1][0] = null;

            if (x + 1 < size.width && y - 1 >= 0) {
               hex = _gameobj._hexes.get((y - 1) * size.width + x + 1);
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[0][1] = hex;
            } else
               moveArray[0][1] = null;
            if (x + 1 < size.width && y - 2 >= 0) {
               hex = _gameobj._hexes.get((y - 2) * size.width + x + 1);
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[1][1] = hex;
            } else
               moveArray[1][1] = null;

            if (x + 1 < size.width && y >= 0) {
               hex = _gameobj._hexes.get(y * size.width + x + 1);
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[0][2] = hex;
            } else // Start odd-number row code
               moveArray[0][2] = null;
            if (x + 2 < size.width && y >= 0) {
               hex = _gameobj._hexes.get(y * size.width + x + 2);
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[1][2] = hex;
            } else
               moveArray[1][2] = null;

            if (x + 1 < size.width && y + 1 <= size.height) {
               hex = _gameobj._hexes.get((y + 1) * size.width + x + 1);
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[0][3] = hex;
            } else
               moveArray[0][3] = null;
            if (x + 1 < size.width && y + 2 <= size.height) {
               hex = _gameobj._hexes.get((y + 2) * size.width + x + 1);
               if (hex != null && hex.hexArea != AREA_ICE_HOME && hex.hexArea != AREA_ICE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[1][3] = hex;
            } else
               moveArray[1][3] = null;
         }
         break;
      case PIECE_ICE:
         if ((y & 0x01) == 0) {
            // If even row, get offsets for valid moves
            //  _\/
            //   /
           if (x >= 0 && y - 1 >= 0) {
               hex = _gameobj._hexes.get((y - 1) * size.width + x);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
               moveArray[0][0] = hex;
            } else
               moveArray[0][0] = null;
            if (x + 1 < size.width && y - 2 >= 0) {
               hex = _gameobj._hexes.get((y - 2) * size.width + x + 1);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
               moveArray[1][0] = hex;
            } else
               moveArray[1][0] = null;

            if (x - 1 >= 0 && y - 1 >= 0) {
               hex = _gameobj._hexes.get((y - 1) * size.width + x - 1);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[0][1] = hex;
            } else
               moveArray[0][1] = null;
            if (x - 1 >= 0 && y - 2 >= 0) {
               hex = _gameobj._hexes.get((y - 2) * size.width + x - 1);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[1][1] = hex;
            } else
               moveArray[1][1] = null;

            if (x - 1 >= 0 && y >= 0) {
               hex = _gameobj._hexes.get(y * size.width + x - 1);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[0][2] = hex;
            } else
               moveArray[0][2] = null;
            if (x - 2 >= 0 && y >= 0) {
               hex = _gameobj._hexes.get(y * size.width + x - 2);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[1][2] = hex;
            } else
               moveArray[1][2] = null;

            if (x - 1 >= 0 && y + 1 <= size.height) {
               hex = _gameobj._hexes.get((y + 1) * size.width + x - 1);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[0][3] = hex;
            } else
               moveArray[0][3] = null;
            if (x - 1 >= 0 && y + 2 <= size.height) {
               hex = _gameobj._hexes.get((y + 2) * size.width + x - 1);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[1][3] = hex;
            } else
               moveArray[1][3] = null;
         } else {
            if (x + 1 < size.width && y - 1 >= 0) {
               hex = _gameobj._hexes.get((y - 1) * size.width + x + 1);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
               moveArray[0][1] = hex;
            } else
               moveArray[0][1] = null;
            if (x + 1 < size.width && y - 2 >= 0) {
               hex = _gameobj._hexes.get((y - 2) * size.width + x + 1);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
               moveArray[1][1] = hex;
            } else
               moveArray[1][1] = null;

            if (x >= 0 && y - 1 >= 0) {
               hex = _gameobj._hexes.get((y - 1) * size.width + x);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[0][0] = hex;
            } else
               moveArray[0][0] = null;
            if (x - 1 >= 0 && y - 2 >= 0) {
               hex = _gameobj._hexes.get((y - 2) * size.width + x - 1);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[1][0] = hex;
            } else
               moveArray[1][0] = null;

            if (x - 1 >= 0 && y >= 0) {
               hex = _gameobj._hexes.get(y * size.width + x - 1);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[0][2] = hex;
            } else
               moveArray[0][2] = null;
            if (x - 2 >= 0 && y >= 0) {
               hex = _gameobj._hexes.get(y * size.width + x - 2);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[1][2] = hex;
            } else
               moveArray[1][2] = null;

            if (x >= 0 && y + 1 <= size.height) {
               hex = _gameobj._hexes.get((y + 1) * size.width + x);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
               moveArray[0][3] = hex;
            } else
               moveArray[0][3] = null;
            if (x - 1 >= 0 && y + 2 <= size.height) {
               hex = _gameobj._hexes.get((y + 2) * size.width + x - 1);
               if (hex != null && hex.hexArea != AREA_FIRE_HOME && hex.hexArea != AREA_FIRE_GOAL && hex.hexType != HEX_FILLED)
                  moveArray[1][3] = hex;
            } else
               moveArray[1][3] = null;
         }
         break;
      }
      return moveArray;
   }
}
